/**
 * 老年代的GC是如何触发的
 * <p>
 * -XX:NewSize=10485760 -XX:MaxNewSize=10485760 -XX:InitialHeapSize=20971520 -XX:MaxHeapSize=20971520
 * -XX:SurvivorRatio=8  -XX:MaxTenuringThreshold=15 -XX:PretenureSizeThreshold=3145728 -XX:+UseParNewGC
 * -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.log
 * 运行日志在根目录gc.log，看不懂就画图。
 */
public class OldGc {
    public static void main(String[] args) {
        byte[] array1 = new byte[4 * 1024 * 1024];
        array1 = null;
        byte[] array2 = new byte[2 * 1024 * 1024];
        byte[] array3 = new byte[2 * 1024 * 1024];
        byte[] array4 = new byte[2 * 1024 * 1024];
        byte[] array5 = new byte[128 * 1024];

        byte[] array6 = new byte[2 * 1024 * 1024];
    }

    /**
     * 这里最关键一个参数，就是“-XX:PretenureSizeThreshold=3145728”
     *
     * 这个参数要设置大对象阈值为3MB，也就是超过3MB，就直接进入老年代。
     *
     * 直接分配了一个4MB的大对象，此时这个对象会直接进入老年代，接着array1不再引用这个对象
     *
     * 连续分配了4个数组，其中3个是2MB的数组，1个是128KB的数组，如下图所示，全部会进入Eden区域中。
     *
     * 接着会执行如下代码：byte[] array6 = new byte[2 * 1024 * 1024];。此时还能放得下2MB的对象吗？不可能了，因为Eden区已经放不下了。因此此时会直接触发一次Young GC。
     *
     * Eden区原来是有7000多KB的对象，但是回收之后发现一个都回收不掉，因为上述几个数组都被变量引用了。
     *
     * 所以此时大家都知道，一定会直接把这些对象放入到老年代里去，但是此时老年代里已经有一个4MB的数组了，还能放的下3个2MB的数组和1个128KB的数组吗？
     *
     * 明显是不行的，此时一定会超过老年代的10MB大小。
     *
     * 大家可以清晰看到，此时执行了CMS垃圾回收器的Full GC，我们之前讲过Full GC其实就是会对老年代进行Old GC，同时一般会跟一次Young GC关联，还会触发一次元数据区（永久代）的GC。
     *
     * 最后在CMS Full GC执行完毕之后，其实年轻代的对象都进入了老年代，此时最后一行代码要在年轻代分配2MB的数组就可以成功了，如下图。
     *
     */
}
